package com.example.base.system.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.base.excetion.GlobalExcetion;
import com.example.base.security.domain.SysMenuEntity;
import com.example.base.security.service.SysMenuService;
import com.example.base.system.domain.SysApi;
import com.example.base.system.domain.SysRoleApi;
import com.example.base.system.domain.vo.SysApiVo;
import com.example.base.system.mapper.SysApiMapper;
import com.example.base.system.service.SysApiService;
import com.example.base.system.service.SysRoleApiService;
import com.example.base.utils.TreeUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.cache.annotation.*;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.cache.annotation.CacheConfig;


import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author X.I.O
 * @since 2024-04-10
 */
@Service
@Transactional
@CacheConfig(cacheNames = "SysApiServiceImpl")
public class SysApiServiceImpl extends ServiceImpl<SysApiMapper, SysApi> implements SysApiService {

    @Autowired
    private SysMenuService sysMenuService;

    @Autowired
    private SysRoleApiService sysRoleApiService;

    @Cacheable(cacheNames = "sysapi",key = "#id")
    @Override
    public SysApi getById(Serializable id){
        return super.getById(id);
    }

    @CacheEvict(cacheNames = "sysapi", key = "#id")
    @Override
    public boolean removeById(Serializable id) {
        return super.removeById(id);
    }

    @CacheEvict(cacheNames = "sysapi", key = "#sysapi.id")
    @Override
    public boolean updateById(SysApi sysapi) {
        return super.updateById(sysapi);
    }

    @Override
    public List<Integer> getApiIdsByRoleId(Serializable roleId) {
        LambdaQueryWrapper<SysRoleApi> lambdaQueryWrapper=new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SysRoleApi::getRoleId,roleId);
        List<SysRoleApi> list=sysRoleApiService.list(lambdaQueryWrapper);
        if(list==null){
            return Collections.EMPTY_LIST;
        }
        return list.stream().map(e->Integer.parseInt(e.getApiId())).collect(Collectors.toList());
    }

    @Override
    public void dealSysApi(String menuId, List<SysApi> sysApis) throws GlobalExcetion {
        if(sysApis==null || sysApis.isEmpty()){
            return;
        }
        List<String> ids=sysApis.stream().filter(e->e.getId()!=null).map(e->String.valueOf(e.getId())).collect(Collectors.toList());
        List<SysApi> sysApiList=this.getSysApisByMenuId(menuId);
        sysApiList.forEach((e)->{
            if(!ids.contains(e.getId().toString())){
                super.removeById(e.getId());
            }
        });
        SysMenuEntity sysMenuEntity=sysMenuService.getById(menuId);
        if(sysMenuEntity==null){
            return;
        }
        for (int i = 0; i < sysApis.size() ; i++) {
            SysApi sysApi=sysApis.get(i);
            if(sysApi.getApiUrl()==null){
                continue;
            }
            if(sysApi.getId()==null){
                //处理新增
                SysApi url=this.getSysApiByUrl(sysApi.getApiUrl());
                if(url!=null){
                    throw new GlobalExcetion(1,sysApi.getApiUrl()+"已被添加过");
                }
                sysApi.setMenuId(menuId);
                sysApi.setCreateTime(new Date());
                sysApi.setDeleted(0);
                sysApi.setIsEnabled(true);
                sysApi.setMenuPid(sysMenuEntity.getParentMenuId());
                super.baseMapper.insert(sysApi);
            }else {
                SysApi entiry=super.baseMapper.selectById(sysApi.getId());
                if(entiry==null){
                    continue;
                }
                if(!entiry.getApiUrl().equals(sysApi.getApiUrl())){
                    SysApi url=this.getSysApiByUrl(sysApi.getApiUrl());
                    if(url!=null){
                        throw new GlobalExcetion(1,sysApi.getApiUrl()+"已被添加过");
                    }
                }
                entiry.setApiName(sysApi.getApiName());
                entiry.setApiUrl(sysApi.getApiUrl());
                entiry.setMenuId(menuId);
                entiry.setMenuPid(sysMenuEntity.getParentMenuId());
                super.baseMapper.updateById(entiry);
            }
        }
    }

    @Override
    public JSONArray getTreeArray() {
        //树tree
        List<SysMenuEntity> treeList=sysMenuService.listTree();
        List<Map> mapTreeList= JSONObject.parseArray(JSONObject.toJSONString(treeList),Map.class);
        JSONArray array=new JSONArray();
        mapTreeList.forEach(e->{
            JSONObject obj=new JSONObject();
            Integer menuId=Integer.valueOf(e.get("id")+"");
            obj.put("id",menuId);
            obj.put("label",e.get("menuName")+" 的api列表");
            obj.put("pid",0);
            array.add(obj);
            Object child=e.get("children");
            if(child!=null){
                List<Map> mapList= (List<Map>) child;
                List<Map<String,Object>> maps=TreeUtils.treeToList("children",mapList);
                List<String> menuIds=maps.stream().map(f->String.valueOf(f.get("id"))).collect(Collectors.toList());
                menuIds.add(menuId+"");
                List<SysApi> apis=getSysApisByMenuIds(menuIds);
                JSONArray arr=new JSONArray();
                if(apis!=null && apis.size() >0){
                    apis.forEach((d)->{
                        JSONObject o=new JSONObject();
                        o.put("id",d.getId());
                        o.put("label",d.getApiName());
                        o.put("pid",menuId);
                        arr.add(o);
                    });
                    obj.put("child",arr);
                }else {
                    obj.put("child",arr);
                }
            }else {
                JSONArray arr=new JSONArray();
                obj.put("child",arr);
            }
        });
        return array;
    }

    @Override
    public List<SysApi> getSysApisByMenuIds(List<String> ids) {
        LambdaQueryWrapper<SysApi> lambdaQueryWrapper=new LambdaQueryWrapper<>();
        lambdaQueryWrapper.in(SysApi::getMenuId,ids);
        return super.list(lambdaQueryWrapper);
    }


    @Override
    public List<SysApi> getSysApisByMenuId(String menuId) {
        LambdaQueryWrapper<SysApi> lambdaQueryWrapper=new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SysApi::getMenuId,menuId);
        return super.baseMapper.selectList(lambdaQueryWrapper);
    }

    @CachePut(cacheNames = "sysapi", key = "#sysapi.id")
    public SysApi saveSysApi(SysApi sysapi) throws GlobalExcetion {
        super.save(sysapi);
        return sysapi;
    }

    @CacheEvict(cacheNames = "sysapi", key = "#sysapi.id")
    public SysApi updateSysApiById(SysApi sysapi) throws GlobalExcetion{
        super.updateById(sysapi);
        return sysapi;
    }


    public SysApi saveOrUpdateSysApi(SysApiVo sysapiVo) throws GlobalExcetion{
        SysApi sysapi=new SysApi();
        BeanUtils.copyProperties(sysapiVo,sysapi);
        if(sysapiVo.getId()!=null){
            SysApi sysapiEntity=super.baseMapper.selectById(sysapiVo.getId());
            if(sysapiEntity==null){
                throw new GlobalExcetion(1,"数据不存在");
            }
            super.baseMapper.updateById(sysapi);
        }else{
            super.baseMapper.insert(sysapi);
        }
        return sysapi;
    }

    public IPage<SysApi> page(Integer page, Integer pageSize) throws GlobalExcetion{
        LambdaQueryWrapper<SysApi> lambdaQueryWrapper=new LambdaQueryWrapper<>();
        IPage<SysApi> iPage=super.baseMapper.selectPage(new Page<>(page,pageSize),lambdaQueryWrapper);
        return iPage;
    }

    @Override
    public SysApi getSysApiByUrl(String url) {
        LambdaQueryWrapper<SysApi> lambdaQueryWrapper=new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SysApi::getApiUrl,url);
        return super.baseMapper.selectOne(lambdaQueryWrapper);
    }
}
